package com.xzc.jcip._2_.线程安全性问题;

import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.ThreadSafe;

import java.math.BigInteger;

/**
 * 减小锁的粒度，在保证消除竞态条件的前提下，尽量减小锁粒度，并将长时间运行的代码
 * 脱离出锁。
 * 优化SynchronizedFactorizer
 */
@ThreadSafe
public class CachedFactorizer {
    @GuardedBy("this")
    private BigInteger lastNumber;
    @GuardedBy("this")
    private BigInteger[] lastFactors;
    @GuardedBy("this")
    private long hits;
    @GuardedBy("this")
    private long cacheHits;

    public synchronized long getHits() {
        return hits;
    }

    public synchronized double getCacheHitRation() {
        return (double) cacheHits / (double) hits;
    }

    public synchronized BigInteger service(BigInteger num) {
        BigInteger i = num;
        BigInteger[] factors = null;
        synchronized (this) {
            //锁的粒度不能太细，加锁与退锁也会消耗
            ++hits;
            if (i.equals(lastNumber)) {
                ++cacheHits;
                factors = lastFactors.clone();
            }
        }
        if (factors == null) {
            //让无状态且耗时可能过长的方法不在锁之内，增加并发性
            factors = factor(i);
            synchronized (this) {
                lastNumber = i;
                lastFactors = factors.clone();
            }
        }
        return i;
    }

    //这个方法可能需要较长时间，而且其本身是无状态的，所以不用加锁
    private BigInteger[] factor(BigInteger i) {
        return new BigInteger[]{};
    }
}
